package com.imooc.maokeyang.alllearning.security.jwt;


import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT token管理类
 */
@Component
@Slf4j
public class JwtTokenUtils {

    public static final String TOKEN_HEADER = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer ";

    /** jwt的秘钥 */
    private String SECRET = "wanghan1031";

    /** token 有效时间  */
    private long EXPIRE = 7200L;

    // 角色的key
    private static final String ROLE_CLAIMS = "role";

    private static final String ISS = "echisan";

    // 选择了记住我之后的过期时间为7天
    private static final long EXPIRATION_REMEMBER = 604800L;

    /**
     * 生成TOKEN
     *
     * @param username
     * @param role
     * @param isRememberMe
     * @return
     */
    public String generateJwtToken(String username, String role, boolean isRememberMe) {
        long expiration = isRememberMe ? EXPIRATION_REMEMBER : EXPIRE;

        // 设置token存储的信息
        Map<String, Object> map = new HashMap<>();
        map.put(ROLE_CLAIMS, role);

        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .setClaims(map)
                .setIssuer(ISS)
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
                .compact();
    }

    /**
     * 从TOKEN中获取用户名
     *
     * @param token
     * @return
     */
    public String getUsername(String token) {
        return getTokenBody(token).getSubject();
    }

    /**
     * 获取用户角色
     *
     * @param token
     * @return
     */
    public String getUserRole(String token){
        return (String) getTokenBody(token).get(ROLE_CLAIMS);
    }


    /**
     * 是否已过期
     *
     * @param token
     * @return
     */
    public boolean isExpiration(String token) {
        try {
            return getTokenBody(token).getExpiration().before(new Date());
        } catch (ExpiredJwtException e) {
            return true;
        }
    }

    /**
     * 验证TOKEN
     *
     * @param token
     * @return
     */
    public boolean validateJwtToken(String token) {
        try {
            Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
            return true;
        } catch (SignatureException e) {
            log.error("Invalid JWT signature: {}", e.getMessage());
        } catch (MalformedJwtException e) {
            log.error("Invalid JWT token: {}", e.getMessage());
        } catch (ExpiredJwtException e) {
            log.error("JWT token is expired: {}", e.getMessage());
        } catch (UnsupportedJwtException e) {
            log.error("JWT token is unsupported: {}", e.getMessage());
        } catch (IllegalArgumentException e) {
            log.error("JWT claims string is empty: {}", e.getMessage());
        }
        return false;
    }

    private Claims getTokenBody(String token){
        return Jwts.parser().setSigningKey(SECRET)
                                .parseClaimsJws(token)
                                    .getBody();
    }
}
